package net.melon.product.inst.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import net.esj.basic.core.view.tools.searcher.SearcherColumn;
import net.esj.basic.dao.jdbc.JdbcDao;
import net.esj.basic.dao.querybuilder.QueryBuilder;
import net.esj.basic.exception.MelonException;
import net.esj.basic.service.impl.DefaultServiceImpl;
import net.esj.basic.utils.Assert;
import net.esj.basic.utils.DateUtils;
import net.esj.basic.utils.Pagination;
import net.esj.basic.utils.StringUtils;
import net.esj.basic.utils.Validators;
import net.melon.product.inst.hibernate.mapping.dto.ProductMapRow;
import net.melon.product.inst.service.ProductService;
import net.melon.product.inst.service.SpecificationsValueService;
import net.melon.product.pojo.Product;
import net.melon.product.pojo.Product.PRODUCT_ENABLE;
import net.melon.product.pojo.ProductAttributeLink;
import net.melon.product.pojo.ProductClassify;
import net.melon.product.pojo.ProductImage;
import net.melon.product.pojo.ProductSku;
import net.melon.product.pojo.ProductSpecifications;
import net.melon.product.pojo.ProductSpecificationsLink;
import net.melon.product.pojo.ProductSpecificationsValue;
import net.melon.product.pojo.dto.ProductImageDto;
import net.melon.product.pojo.dto.ProductSpecificationsValueDto;
import net.melon.stock.pojo.Stock;
import net.web.dto.BaseParam;
import net.web.dto.ClassifyDto;
import net.web.dto.ProductDto;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("productService")
public class ProductServiceImpl extends DefaultServiceImpl implements ProductService {
	
	@Resource
	private ClassifyCacheProxy classifyCacheProxy;
	
	//@Resource
	//private SpecificationsValueCacheProxy specificationsValueCacheProxy;

	@Resource
	private SpecificationsValueService specificationsValueService;
	
	@Override
	public ProductImageDto getProductImageDto(String productId) {
		Product product = get(productId, Product.class);
		Assert.notNull(product);
		ProductImageDto dto = new ProductImageDto();
		dto.setProduct(product);
		List<ProductImage> list =  getProductImageList(productId);
		dto.setImages(list);
		return dto;
	}
	@Override
	public List<ProductImage> getProductImageList(String productId) {
		QueryBuilder<ProductImage> qb = createQueryBuilder(ProductImage.class);
		qb.eq("productId", productId);
		List<ProductImage> list =  queryListByQueryBuilder(qb);
		return list;
	}

	@Transactional
	@Override
	public void addProduct(Product entity, List<String> picnames) {
		if(!StringUtils.hasText(entity.getSerial())){
			throw new MelonException("请填写编号");
		}
		/*if(Validators.isEmpty(entity.getProductSkus())){
			throw new MelonException("产品规格必须选择");
		}*/
		if(entity.getMarketEnable()==PRODUCT_ENABLE.YES.getMarketEnable() ){
			entity.setMarketTime(DateUtils.now());
		}
		entity.setState(1);
		save(entity);
		if(!Validators.isEmpty(picnames)){
			for(String v : picnames){
				ProductImage image = new ProductImage(entity.getId(),v);
				save(image);
			}
		}
		if(!Validators.isEmpty(entity.getSpecifications())){
			for(ProductSpecificationsLink link : entity.getSpecifications()){
				link.setProductId(entity.getId());
				save(link);
			}
		}
	}

	private String getNumber(String serial,String index) {
		String number = index;
		for(int i=5;i>index.length();i--){
			number = "0"+number;
		}
		return serial +"-"+ number;
	}

	@Override
	public Product getProduct(String id,boolean withClassify,boolean withImages,boolean withSku,boolean withSpecifications,boolean withAttribute) {
		Product product = get(id, Product.class);
		if(withClassify){
			ProductClassify classify = classifyCacheProxy.getClassify(product.getClassifyId());
			product.setClassify(classify);
		}
		if(withImages){
			List<ProductImage> images = getProductImageList(id);
			product.getImages().addAll(images);
		}
		if(withSpecifications){
			List<ProductSpecificationsLink> specifications = getProductSpecificationsLinkList(id);
			product.getSpecifications().addAll(specifications);
		}
		return product;
	}
	
	@Override
	public List<ProductAttributeLink> getProductAttributeList(String productId) {
		QueryBuilder<ProductAttributeLink> qb = createQueryBuilder(ProductAttributeLink.class);
		qb.eq("productId", productId);
		return queryListByQueryBuilder(qb);
	}
	@Override
	public List<ProductSku> getProductSkuList(String productId) {
		QueryBuilder<ProductSku> qb = createQueryBuilder(ProductSku.class);
		qb.eq("productId", productId);
		List<ProductSku> list = queryListByQueryBuilder(qb);
		for(ProductSku sku : list){
			sku.setDtos(getProductSkuDtos(sku));
		}
		return list;
	}
	
	private List<ProductSpecificationsValueDto> getProductSkuDtos(ProductSku sku) {
		String groupId = sku.getGroupId();
		String[] groupArr = groupId.split("-");
		Map<Long,ProductSpecificationsValueDto> map = new HashMap<Long, ProductSpecificationsValueDto>(); 
		for(String s : groupArr){
			ProductSpecificationsValue value = specificationsValueService.getProductSpecificationsValue(Long.valueOf(s));
			ProductSpecificationsValueDto dto = null;
			if(!map.containsKey(value.getSpecifications().getId())){
				dto = new ProductSpecificationsValueDto();
				dto.setProductSpecifications(get(value.getSpecifications().getId(), ProductSpecifications.class));
			}else{
				dto = map.get(value.getSpecifications().getId());
			}
			dto.getList().add(value);
			map.put(value.getSpecifications().getId(), dto);
		}
		return new ArrayList<>(map.values());
	}
	@Override
	public List<ProductSpecificationsLink> getProductSpecificationsLinkList(String productId) {
		QueryBuilder<ProductSpecificationsLink> qb = createQueryBuilder(ProductSpecificationsLink.class);
		qb.eq("productId", productId).OrderByAsc("productId");
		return queryListByQueryBuilder(qb);
	}
	@Transactional
	@Override
	public void updateProduct(Product entity, List<String> picnames) {
		Product prduct = get(entity.getId(), Product.class);
		if(prduct.getMarketEnable()==PRODUCT_ENABLE.NO.getMarketEnable() && entity.getMarketEnable()==PRODUCT_ENABLE.YES.getMarketEnable() ){
			prduct.setMarketTime(DateUtils.now());
		}
		prduct.setMarketEnable(entity.getMarketEnable());
		prduct.setName(entity.getName());
		prduct.setSerial(entity.getSerial());
		prduct.setPrice(entity.getPrice());
		prduct.setFloorReferencePrice(entity.getFloorReferencePrice());
		prduct.setGuidePrice(entity.getGuidePrice());
		prduct.setContent(entity.getContent());
		update(prduct);
		getDao(JdbcDao.class).getJdbcTemplate().update("DELETE FROM ML_PRODUCT_SPECIFICATIONS_LINK WHERE PRODUCT_ID = ? ", new Object[]{entity.getId()});
		if(!Validators.isEmpty(entity.getSpecifications())){
			for(ProductSpecificationsLink link : entity.getSpecifications()){
				link.setProductId(entity.getId());
				save(link);
			}
		}
		if(!Validators.isEmpty(picnames)){
			for(String v : picnames){
				ProductImage image = new ProductImage(entity.getId(),v);
				save(image);
			}
		}
	}
	@Override
	public void deleteImage(String imageId) {
		ProductImage image = get(Long.valueOf(imageId), ProductImage.class);
		Assert.notNull(image);
		File file = new File(Product.ICON_SUB_DIR + File.pathSeparator + image.getIcon());
		file.deleteOnExit();
		delete(image);
	}
	
	@Transactional
	@Override
	public void editStock(String id,List<ProductSku> productSkus) {
		for(ProductSku sku : productSkus){
			ProductSku s = get(sku.getId(), ProductSku.class);
			s.setPrice(sku.getPrice());
		}
	}
	
	
	@Override
	public void marketEnable(String id, int state) {
		Product product = get(id, Product.class);
		Assert.notNull(product);
		if(state==PRODUCT_ENABLE.YES.getMarketEnable()){
			if(product.getMarketEnable()==PRODUCT_ENABLE.NO.getMarketEnable()){
				product.setMarketEnable(PRODUCT_ENABLE.YES.getMarketEnable());
			}
		}
		if(state==PRODUCT_ENABLE.NO.getMarketEnable()){
			if(product.getMarketEnable()==PRODUCT_ENABLE.YES.getMarketEnable()){
				product.setMarketEnable(PRODUCT_ENABLE.NO.getMarketEnable());
			}
		}
	}
	
	private static String PRODUCT_PAGE = "SELECT p.* , pc.name c_name FROM ML_PRODUCT_CLASSIFY pc,ML_PRODUCT p WHERE p.CLASSIFY_ID = pc.ID AND p.STATE = 1 ";
	//private static String PRODUCT_PAGE = "SELECT p.*,c.NAME c_name FROM stock s LEFT JOIN ML_PRODUCT p ON p.ID = s.PRODUCT LEFT JOIN ML_PRODUCT_CLASSIFY c ON p.CLASSIFY_ID = c.ID ";
	
	@Override
	public Pagination<Product> productPage(Pagination<Product> pagination) {
		StringBuffer sb = new StringBuffer(PRODUCT_PAGE);
		for(SearcherColumn sc : pagination.getSearcher().getColumns()){
			switch (sc.getKey()) {
			case "name":
				sb.append(" AND p.NAME like '%" + sc.getValue().toString()+"%'");
				break;
			case "classifyId":
				sb.append(" AND p.CLASSIFY_ID = " + Long.valueOf(sc.getValue().toString())+"");
				break;
			default:
				break;
			}
		}
		if(!pagination.getSearcher().getOrders().isEmpty()){
			sb.append(" ORDER BY ");
		}
		for(SearcherColumn sc : pagination.getSearcher().getOrders()){
			switch (sc.getKey()) {
			case "serial":
				sb.append(" SERIAL "+sc.getValue());
				break;
			default:
				break;
			}
		}
		pagination = ((JdbcDao)dao).queryPage(sb.toString(), new ProductMapRow(), pagination,"");
		return pagination;
	}
	
	private static String HOT_CAR_LIST = "SELECT p.*,c.NAME c_name,s.COUNT FROM stock s LEFT JOIN ML_PRODUCT p ON p.ID = s.PRODUCT LEFT JOIN ML_PRODUCT_CLASSIFY c ON p.CLASSIFY_ID = c.ID WHERE s.COUNT>0 AND p.STATE = 1  AND  p.MARKET_ENABLE = "+PRODUCT_ENABLE.YES.getMarketEnable();
										 
	
	@Override
	public List<ProductDto> getHotCarList(Long regionId,int limit) throws MelonException,Exception {
		StringBuffer sb = new StringBuffer(HOT_CAR_LIST);
		if(regionId!=null){
			sb.append(" AND s.REGION = '"+regionId+"'");
		}
		sb.append(" GROUP BY p.CLASSIFY_ID ORDER BY CLICK DESC  ");
		
		sb.append(" LIMIT 0,"+limit);
		List<Product> productList = getDao(JdbcDao.class).getJdbcTemplate().query(sb.toString(), new ProductMapRow());
		List<ProductDto> dtos = new ArrayList<ProductDto>();
		for(Product product : productList){
			if(product.getId()!=null){
				ProductDto dto = new ProductDto();
				BeanUtils.copyProperties(dto, product);
				List<ProductImage> images = getProductImageList(product.getId());
				if(!Validators.isEmpty(images)){
					dto.setIcon(images.get(0).getIcon());
				}
				dto.setClassifyName(new ClassifyDto(new BaseParam(String.valueOf(product.getClassify().getId()),product.getClassify().getName())));
				dtos.add(dto);
			}
		}
		return dtos;
	}
	
	@Override
	public void click(String productId) {
		Product product = get(productId, Product.class);
		product.setClick(product.getClick() + 1);
		update(product);
	}
	
	
	@Override
	public int getProductCountByClassify(Long classifyId) {
		QueryBuilder<Product> qb = createQueryBuilder(Product.class);
		qb.eq("classifyId", classifyId).eq("state", 1);
		return queryCountByQueryBuilder(qb);
	}
	
	@Override
	public void deleteProduct(String deletes) {
		Product product = get(deletes, Product.class);
		QueryBuilder<Stock> qb = createQueryBuilder(Stock.class);
		qb.eq("product", product);
		if(queryCountByQueryBuilder(qb)==0){
			product.setState(-1);
			product.setMarketEnable(PRODUCT_ENABLE.NO.getMarketEnable());
			update(product);
		}else{
			throw new MelonException("该商品已经进入库存，不能删除");
		}
		
	}
	private static String SELECT_PRODUCT_BY_CLASSIFY_STOCK = " SELECT p.*,c.NAME c_name,s.COUNT FROM stock s LEFT JOIN ML_PRODUCT p ON p.ID = s.PRODUCT LEFT JOIN ML_PRODUCT_CLASSIFY c ON p.CLASSIFY_ID = c.ID WHERE  p.CLASSIFY_ID = ? AND p.STATE = 1  AND  p.MARKET_ENABLE = "+PRODUCT_ENABLE.YES.getMarketEnable() ;
	
	@Override
	public List<Product> getProductByClassifyAndStock(Long classifyId, boolean withStock) {
		StringBuffer sb = new StringBuffer(SELECT_PRODUCT_BY_CLASSIFY_STOCK);
		
		if(withStock){
			sb.append(" AND s.COUNT>0 ");
		}
		
		List<Product> productList = getDao(JdbcDao.class).getJdbcTemplate().query(sb.toString(), new ProductMapRow(),new Object[]{classifyId});
		
		return productList;
	}
	
	
}
